package com.zx.idc.backend.gui.api.management.basicdata.common;

import com.zx.idc.cache.entity.HotDomainMetaInfo;
import com.zx.idc.cache.entity.HotIpMetaInfo;
import com.zx.idc.cache.slog.SlogHotDomainCacheService;
import com.zx.idc.cache.slog.SlogHotIpCacheService;
import com.zx.idc.common.constants.CommonConstant;
import com.zx.idc.common.lang.DateUtil;
import com.zx.idc.common.util.DateFormatterStringEnum;
import com.zx.idc.common.util.LocalDateTimeFormatUtil;
import com.zx.idc.ds.base.cus.service.IBaseServiceInfoService;
import com.zx.idc.ds.base.house.entity.BaseServiceInfo;
import com.zx.idc.ds.base.serve.entity.BaseServiceDomain;
import com.zx.idc.ds.base.serve.service.IBaseServiceDomainService;
import com.zx.idc.ds.common.constant.ReportStatusConstant;
import com.zx.idc.ds.slog.entity.SlogAbnormalIp;
import com.zx.idc.ds.slog.entity.SlogHotIp;
import com.zx.idc.ds.slog.entity.SlogHotIpDomain;
import com.zx.idc.ds.slog.entity.SlogIllegalSite;
import com.zx.idc.ds.slog.service.ISlogAbnormalIpService;
import com.zx.idc.ds.slog.service.ISlogHotIpDomainService;
import com.zx.idc.ds.slog.service.ISlogIllegalSiteService;
import com.zx.idc.ds.slog.vo.AbnormalIpAndSiteMergeVo;
import com.zx.idc.ds.slog.vo.SlogAbnormalIpVo;
import com.zx.idc.ds.slog.vo.SlogIllegalSiteVo;
import com.zx.idc.xml.entity.idcmonitor.housemonitor.HouseMonitor;
import com.zx.idc.xml.entity.idcmonitor.housemonitor.illegalinfo.IllegalInfo;
import com.zx.idc.xml.entity.idcmonitor.housemonitor.ipinfo.IpInfo;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.time.LocalDateTime;
import java.util.*;
import java.util.stream.Collectors;

/**
 * 将业务系统的实体转换为 IDC 监测 XML Bean
 *
 * @author rxliuli
 */
@Service
@Transactional(rollbackFor = Exception.class)
public class MonitorService {
    private static final String VAL_NA = "NA";
    @Autowired
    private ISlogAbnormalIpService iSlogAbnormalIpService;

    @Autowired
    private ISlogHotIpDomainService iSlogHotIpDomainService;

    @Autowired
    private IBaseServiceDomainService iBaseServiceDomainService;

    @Autowired
    private IBaseServiceInfoService iBaseServiceInfoService;

    @Autowired
    private ISlogIllegalSiteService iSlogIllegalSiteService;

    @Autowired
    private SlogHotIpCacheService slogHotIpCacheService;
    @Autowired
    private SlogHotDomainCacheService hotDomainCacheService;


    /**
     * 将异常 ip 监测数据转换为 XML Bean 11.4 表 34
     */
    public HouseMonitor slogIllegalSiteTotHouseMonitor(SlogIllegalSite sis) {
        SlogAbnormalIp slogAbnormalIp = iSlogAbnormalIpService.selectFirst(
            new SlogAbnormalIp()
                .setReportStatus(ReportStatusConstant.NOT_REPORTED)
                .setHouseId(sis.getHouseId())
        );
        IpInfo ipInfo = null;
        if (Objects.nonNull(slogAbnormalIp)) {
            ipInfo = new IpInfo().setRegError(slogAbnormalIp.getExceptionType())
                .setRegDomain(slogAbnormalIp.getRegDomain());
        }
        return new HouseMonitor(
            sis.getHouseId(),
            sis.getIp(),
            sis.getPort(),
            sis.getDomain(),
            Arrays.stream(sis.getServiceContent().split(",")).map(Integer::parseInt).collect(Collectors.toList()),
            formatDate(sis.getFirstFound()),
            formatDate(sis.getLastFound()),
            new IllegalInfo(sis.getIllegalType(),
                sis.getDealStatus(),
                sis.getOperationAccount()),
            ipInfo,
            sis.getVisitCount(),
            sis.getProtocol()
        );
    }

    public HouseMonitor slogAbnormalIpTotHouseMonitor(SlogAbnormalIp sai) {
        return new HouseMonitor(
            sai.getHouseId(),
            sai.getIp(),
            sai.getPort(),
            sai.getRegDomain(),
            null,
            formatDate(sai.getFstFoundTime()),
            formatDate(sai.getLastFoundTime()),
            new IllegalInfo(sai.getExceptionType(),
                sai.getDealStatus(),
                sai.getDealUser()),
            new IpInfo(
                sai.getRegType(),
                sai.getRegDomain()
            ),
            sai.getVisitCount(),
            sai.getProtocol()
        );
    }

    /**
     * 获取零上报数据
     *
     * @param houseId
     * @return
     */
    public HouseMonitor getZeroReportData(Long houseId) {
        String time = LocalDateTimeFormatUtil.formatLocalDateTime(LocalDateTime.now(), DateFormatterStringEnum.HORIZONTAL_LINE_YYYY_MM_DD_HH_MM_SS);
        return new HouseMonitor()
            .setId(houseId)
            .setReportNA(VAL_NA)
            .setFirstFound(time)
            .setLastFound(time)
            .setVisitCount(0L)
            .setPort(0)
            .setIp("")
            .setProtocol(0);
    }

    private String formatDate(LocalDateTime localDateTime) {
        return LocalDateTimeFormatUtil.formatLocalDateTime(
            localDateTime,
            DateFormatterStringEnum.HORIZONTAL_LINE_YYYY_MM_DD_HH_MM_SS
        );
    }


    /**
     * 根据活跃ip转换机房检测数据
     *
     * @param slogHotIp
     * @return
     */
    @Deprecated
    public HouseMonitor slogHotIpToHouseMonitor(SlogHotIp slogHotIp) {
        //尝试寻找域名
        //关系: ip -> 域名 -> 服务信息
        SlogHotIpDomain slogHotIpDomain = iSlogHotIpDomainService.selectFirst(new SlogHotIpDomain().setIp(slogHotIp.getFindIpListIp()));
        List<Integer> serviceType = null;
        IpInfo ipInfo = null;
        IllegalInfo illegalInfo = null;
        String domain = "";
        if (slogHotIpDomain != null) {
            domain = slogHotIpDomain.getDomain();
            if (StringUtils.isNotEmpty(domain)) {
                BaseServiceDomain baseServiceDomain = iBaseServiceDomainService.selectFirst(new BaseServiceDomain().setDomain(domain));
                if (Objects.nonNull(baseServiceDomain) && Objects.nonNull(baseServiceDomain.getServiceId())) {
                    BaseServiceInfo baseServiceInfo = iBaseServiceInfoService.selectById(baseServiceDomain.getServiceId());
                    serviceType = Arrays.stream(baseServiceInfo.getServiceContent().split(",")).map(Integer::valueOf).collect(Collectors.toList());
                }
                SlogIllegalSite slogIllegalSite = iSlogIllegalSiteService.selectFirst(
                    new SlogIllegalSite()
                        .setReportStatus(ReportStatusConstant.NOT_REPORTED)
                        .setHouseId(slogHotIp.getHouseId())
                        .setDomain(domain)
                );

                if (slogIllegalSite != null) {
                    illegalInfo = new IllegalInfo().setIllegalType(slogIllegalSite.getIllegalType())
                        .setCurrentState(slogIllegalSite.getDealStatus())
                        .setUser(slogIllegalSite.getOperationAccount());
                    //更新上报状态
                    slogIllegalSite.setReportStatus(ReportStatusConstant.REPORTING);
                    iSlogIllegalSiteService.updateById(slogIllegalSite);
                }

                SlogAbnormalIp slogAbnormalIp = iSlogAbnormalIpService.selectFirst(
                    new SlogAbnormalIp()
                        .setReportStatus(ReportStatusConstant.NOT_REPORTED)
                        .setHouseId(slogHotIp.getHouseId())
                        .setIp(slogHotIp.getFindIpListIp())
                );
                if (Objects.nonNull(slogAbnormalIp)) {
                    ipInfo = new IpInfo().setRegDomain(slogAbnormalIp.getRegDomain())
                        .setRegError(slogAbnormalIp.getExceptionType());
                    //更新上报状态
                    slogAbnormalIp.setReportStatus(ReportStatusConstant.REPORTING);
                    iSlogAbnormalIpService.updateById(slogAbnormalIp);
                }

            }
        }
        //获取24小时访问量
        HotIpMetaInfo hotIpMetaInfo = slogHotIpCacheService.getMeta(slogHotIp.getHouseId(), slogHotIp.getFindIpListIp());
        Optional.ofNullable(hotIpMetaInfo).ifPresent(metaInfo -> slogHotIp.setNewVisitsCount(metaInfo.getNewVisitsCount()));

        return new HouseMonitor()
            .setId(slogHotIp.getHouseId())
            .setFirstFound(formatDate(slogHotIp.getFindIpListFirstTime()))
            .setLastFound(formatDate(slogHotIp.getFindIpListLastTime()))
            .setVisitCount(slogHotIp.getNewVisitsCount())
            .setPort(slogHotIp.getPort())
            .setProtocol(slogHotIp.getProtocol())
            .setIp(slogHotIp.getFindIpListIp())
            .setServiceType(serviceType)
            .setDomain(domain)
            .setIllegalInfo(illegalInfo)
            .setIpInfo(ipInfo);
    }


    /**
     * 查询未上报的 “基础数据监测异常记录”
     * @param houseId 机房id
     * @return
     */
    public List<HouseMonitor> queryBaseAbnormalData(Long houseId){
        SlogAbnormalIpVo queryParam = new SlogAbnormalIpVo();
        queryParam.setHouseId(houseId).setReportStatus(ReportStatusConstant.NOT_REPORTED);
        List<SlogAbnormalIpVo> abnormalIpList = iSlogAbnormalIpService.listByParam(queryParam);
        List<HouseMonitor> houseMonitorList = wrapperAbnormalIpUploadData(abnormalIpList);
        return houseMonitorList;
    }


    /**
     * 把异常IP封装成上报格式
     * @param abnormalIpList 异常IP列表
     * @return 封装后的数据
     */
    public List<HouseMonitor> wrapperAbnormalIpUploadData(List<SlogAbnormalIpVo> abnormalIpList){
        List<HouseMonitor> houseMonitorList = new ArrayList<HouseMonitor>();
        abnormalIpList.stream().forEach(abnormalIpVo -> {
            Integer serviceType = 24;
            LocalDateTime firstFoundTime = null;
            LocalDateTime lastFoundTime = null;  //lastfoundTime 以缓存meta信息里面记录的为准，如果找不到就以数据库的为准
            Integer protocol = null;
            IpInfo ipInfo = null;

            String dealUser = abnormalIpVo.getDealUser();
            if(org.springframework.util.StringUtils.isEmpty(dealUser)){
                dealUser = "ISMS";
            }
            IllegalInfo illegalInfo = new IllegalInfo().setIllegalType(0)
                .setCurrentState(abnormalIpVo.getDealStatus())
                .setUser(dealUser);

            ipInfo = new IpInfo().setRegDomain(abnormalIpVo.getRegDomain())
                .setRegError(abnormalIpVo.getExceptionType());
            //更新上报状态
            abnormalIpVo.setReportStatus(ReportStatusConstant.REPORTING);
            iSlogAbnormalIpService.updateById(abnormalIpVo);
            firstFoundTime = abnormalIpVo.getFstFoundTime();
            lastFoundTime = abnormalIpVo.getLastFoundTime();
            protocol = abnormalIpVo.getProtocol();

            //获取24小时访问量
            HotIpMetaInfo metaInfo = slogHotIpCacheService.getMeta(abnormalIpVo.getHouseId(), abnormalIpVo.getIp());

            HouseMonitor houseMonitor = new HouseMonitor()
                .setId(abnormalIpVo.getHouseId())
                .setFirstFound(formatDate(firstFoundTime))
                .setLastFound(metaInfo==null ? LocalDateTimeFormatUtil.formatLocalDateTime(lastFoundTime, CommonConstant.DEFAULT_DATE_PATTERN) : DateUtil.formatDate(metaInfo.getLstFoundTime(), "yyyy-MM-dd HH:mm:ss"))
                .setVisitCount(metaInfo==null ? abnormalIpVo.getVisitCount() : metaInfo.getNewVisitsCount())
                .setPort(abnormalIpVo.getPort())
                .setProtocol(protocol)
                .setIp(abnormalIpVo.getIp())
                .setServiceType(Arrays.asList(serviceType))
                .setDomain(abnormalIpVo.getActualDomain())
                .setIllegalInfo(illegalInfo)
                .setIpInfo(ipInfo);
            houseMonitorList.add(houseMonitor);
        });
        return houseMonitorList;
    }



}
